<?php

namespace app\api\controller;

use app\common\controller\Api;
use app\common\model\general\LihuaCity;
use app\common\model\goods\LihuaStock;
use app\common\model\LihuaOrder;
use app\common\model\LihuaOrderGoods;
use app\common\model\LihuaUserbonus;
use think\Db;
use think\Exception;
use think\Validate;

/**
 * 订单
 */
class Order extends Api
{
    protected $noNeedLogin = ['*'];
    protected $noNeedRight = ['*'];

    /**
     * 提交订单
     *
     * @ApiMethod   (POST)
     * @ApiHeaders  (name=token, type=string, required=true, description="请求Token，游客不传")
     * @ApiParams   (name="platform", type="string", required=true, description="平台，值为app或xcx")
     * @ApiParams   (name="city_id", type="int", required=true, description="城市ID")
     * @ApiParams   (name="pay_type", type="int", required=true, description="支付方式：1=支付宝支付，2=微信支付，3=丽华钱包，4=货到付款")
     * @ApiParams   (name="addr_id", type="int", required=true, description="收货地址ID，会员必要")
     * @ApiParams   (name="consignee", type="string", required=true, description="收货人，游客必要")
     * @ApiParams   (name="mobile", type="string", required=true, description="收货手机，游客必要")
     * @ApiParams   (name="name", type="string", required=true, description="地址名称，游客必要")
     * @ApiParams   (name="house_num", type="string", required=true, description="地址门牌，游客必要")
     * @ApiParams   (name="lng", type="string", required=true, description="地址经度，游客必要")
     * @ApiParams   (name="lat", type="string", required=true, description="地址纬度，游客必要")
     * @ApiParams   (name="goods_nums", type="string", required=true, description="商品ID及数量键值对JSON字符串")
     * @ApiParams   (name="bonus_id", type="int", required=false, description="用户红包ID，默认0不使用红包")
     * @ApiParams   (name="deliver_time", type="string", required=true, description="送餐时间")
     * @ApiParams   (name="tableware", type="int", required=false, description="餐具：0=不需要，1=需要")
     * @ApiParams   (name="invo_id", type="int", required=false, description="发票ID，默认0不需要发票")
     * @ApiParams   (name="invo_type", type="int", required=false, description="发票类型，游客可传")
     * @ApiParams   (name="invo_title", type="string", required=false, description="发票抬头，游客可传")
     * @ApiParams   (name="taxno", type="string", required=false, description="发票税号，游客可传")
     * @ApiParams   (name="remark", type="string", required=false, description="订单备注")
     * @ApiReturn   ({"code":1,"msg":"OK","time":"1567010784","data":{"order_id":"1","sn":"190925460938715"}})
     */
    public function post()
    {
        $this->request->filter('trim,strip_tags');
        $city_id      = (int)$this->request->post('city_id', 0);
        $platform     = strtolower($this->request->post('platform'));
        $pay_type     = $this->request->post('pay_type', 0);//支付方式
        $tableware    = $this->request->post('tableware', 0);//需要餐具
        $goods_nums   = $this->request->post('goods_nums', '');//商品及数量
        $deliver_time = $this->request->post('deliver_time', '');//送餐时间
        $remark       = $this->request->post('remark', '');//备注信息

        if (!$city_id) $this->error('非法操作');
        if (!in_array($platform, ['app', 'xcx'])) $this->error('非法操作');
        if (!in_array($pay_type, [1, 2, 3, 4]))   $this->error('非法操作');

        if (!$goods_nums)   $this->error('请选择商品');
        if (!$deliver_time) $this->error('请选择送餐时间');
        if (mb_strlen($remark) > 50) $this->error('订单备注请在50个字以内');

        $goods_nums = json_decode($goods_nums, true);
        if (json_last_error()) $this->error('商品数据异常');

        $addr  = [];
        $bonus = ['id' => 0, 'name' => '', 'fee' => 0];
        $invo  = ['type' => 0, 'title' => '', 'taxno' => ''];
        $bonus_reach = 0;

        if ($this->token) {
            $user_id  = $this->auth->id;
            $addr_id  = $this->request->post('addr_id', 0);//用户地址id
            $bonus_id = $this->request->post('bonus_id', 0);//用户红包id
            $invo_id  = $this->request->post('invo_id', 0);//用户发票id

            if ($addr_id > 0) {
                $addr = \app\common\model\LihuaUseraddr::where(['id' => $addr_id, 'user_id' => $user_id])->find();
                if (!$addr) $this->error('送餐地址已失效');
            } else {
                $this->error('请选择送餐地址');
            }

            if ($bonus_id > 0) {
                $row = LihuaUserbonus::where(['id' => $bonus_id, 'user_id' => $user_id])->find();
                if ($row && $row['status'] == 0 && $row['end_date'] >= date('Y-m-d')) {
                    $bonus = ['id' => $row['id'], 'name' => $row['name'], 'fee' => round($row['reduce'], 2)];
                    $bonus_reach = $row['reach'];
                } else {
                    $this->error('红包已失效');
                }
            }

            if ($invo_id > 0) {
                $row = \app\common\model\LihuaUserinvo::where(['id' => $invo_id, 'user_id' => $user_id])->find();
                if ($row) {
                    $invo = ['type' => $row['type'], 'title' => $row['title'], 'taxno' => $row['taxno']];
                } else {
                    $this->error('发票信息已失效');
                }
            }

        } else {
            $user_id = 0;
            //游客送餐地址信息
            $consignee = $this->request->post('consignee');
            $mobile    = $this->request->post('mobile');
            $name      = $this->request->post('name');
            $house_num = $this->request->post('house_num');
            $lng       = $this->request->post('lng');
            $lat       = $this->request->post('lat');
            if (!$mobile || !$name || !$house_num || !is_numeric($lng) || !is_numeric($lat)) $this->error('地址错误');

            $len = mb_strlen($consignee);
            if ($len < 2 || $len > 12 || !Validate::is($consignee, 'chs')) $this->error('姓名只允许2~12个汉字');
            if (!Validate::regex($mobile, "^1\d{10}$")) $this->error('手机号格式错误');

            $store = \app\common\model\general\LihuaStore::getPointStore($city_id, $lng, $lat);
            if ($store['id'] == 0) $this->error('地址不在配送范围内');

            $addr = [
                'city_id'    => $store['city_id'],
                'store_id'   => $store['id'],
                'store_name' => $store['name'],
                'consignee'  => $consignee,
                'mobile'     => $mobile,
                'name'       => $name,
                'house_num'  => $house_num,
                'lng'        => $lng,
                'lat'        => $lat,
            ];

            //游客发票信息
            $invo_type  = $this->request->post('invo_type', 0);
            $invo_title = $this->request->post('invo_title', '');
            $invo_taxno = $this->request->post('taxno', '');
            if (!in_array($invo_type, [0,1,2,3])) $this->error('发票类型错误');
            if (mb_strlen($invo_title) > 50)      $this->error('发票抬头过长');
            if (mb_strlen($invo_taxno) > 30)      $this->error('发票税号过长');

            $invo = [
                'type'  => $invo_type,
                'title' => $invo_title,
                'taxno' => $invo_taxno,
            ];
        }

        //商品信息
        $goods = \app\common\model\goods\LihuaGoods::getCartGoodsList($addr['store_id'], $goods_nums);
        if ($goods['goods_nums'] != $goods_nums) $this->error('有商品已失效，请重新选择');
        if (!$goods['alone_sale'])       $this->error('请选择一份主食，配餐商品单点不送');
        if ($goods['lack_goods']['ids']) $this->error(join('、', $goods['lack_goods']['names']) . ' 库存不足');

        //城市信息
        $city = LihuaCity::getCityInfo($addr['city_id']);
        if ($goods['goods_amount'] < $city['min_price']) $this->error('商品起送价￥' . $city['min_price']);

        //判断商品金额是否满足红包满减金额
        if ($bonus_reach > 0 && $goods['goods_amount'] < $bonus_reach) $this->error('非法操作');

        //城市满减
        $enough = LihuaCity::countEnough($city['enough'], $goods['goods_amount']);

        //订单号
        $sn = date('ym') . sprintf("%05d", mt_rand(1, 99999)) . date('d') .
              sprintf("%05d", mt_rand(1, 99999));

        //订单金额
        $discount = round($enough['reduce'] + $bonus['fee'], 2);
        $original_amount = round($goods['goods_amount'] + $goods['packing_fee'] + $city['deliver_fee'], 2);
        $order_amount = round($original_amount - $discount, 2);
        if ($order_amount < 0) $order_amount = 0;

        //订单数据
        $data = [
            'sn'              => $sn,
            'user_id'         => $user_id,
            'city_id'         => $addr['city_id'],
            'city_name'       => $city['city_name'],
            'store_id'        => $addr['store_id'],
            'store_name'      => $addr['store_name'],
            'consignee'       => $addr['consignee'],
            'mobile'          => $addr['mobile'],
            'address'         => $addr['name'] . $addr['house_num'],
            'lng'             => $addr['lng'],
            'lat'             => $addr['lat'],
            'packing_fee'     => $goods['packing_fee'],
            'deliver_fee'     => $city['deliver_fee'],
            'enough_name'     => $enough['name'],//满减名称
            'enough_fee'      => $enough['reduce'],//满减金额
            'bonus_name'      => $bonus['name'],//红包名称
            'bonus_fee'       => $bonus['fee'],//红包金额
            'deliver_time'    => date('Y-m-d ') . $deliver_time . ':00',
            'tableware'       => $tableware,
            'invo_type'       => $invo['type'],//发票类型
            'invo_title'      => $invo['title'],//发票抬头
            'invo_taxno'      => $invo['taxno'],//发票税号
            'remark'          => $remark,//备注
            'goods_amount'    => $goods['goods_amount'],
            'original_amount' => $original_amount,//商品费+餐盒费+送餐费
            'order_amount'    => $order_amount,//商品费+餐盒费+送餐费-满减费-红包费
            'discount'        => $discount,//满减费+红包费
            'platform'        => $platform,
            'pay_type'        => $pay_type,
            'add_time'        => date('Y-m-d H:i:s'),
            'status'          => $pay_type == 4 ? 2 : 1,//1待支付，货到付款直接进入2待确认
        ];

        //创建订单
        $order_id = 0;
        Db::startTrans();
        try {
            $order = LihuaOrder::create($data);
            Db::commit();
            $order_id = $order->id;
        } catch (Exception $e) {
            Db::rollback();
            $this->error('提交失败，请尝试重新提交');
        }

        //更新红包已使用
        if ($bonus['id'] > 0) {
            LihuaUserbonus::update(['status' => 1, 'order_sn' => $sn], ['id' => $bonus['id']]);
        }

        //商品减库存
        if ($goods['goods_stocks']) {
            foreach ($goods_nums as $k => $v) {
                if (isset($goods['goods_stocks'][$k])) {
                    LihuaStock::where(['goods_id' => $k, 'store_id' => $addr['store_id']])->setDec('num', $v);
                }
            }
        }

        //保存商品信息
        $orderGoods = [];
        foreach ($goods['goods'] as $k => $v) {
            $orderGoods[] = [
                'order_id'    => $order_id,
                'order_sn'    => $sn,
                'city_id'     => $addr['city_id'],
                'store_id'    => $addr['store_id'],
                'user_id'     => $user_id,
                'goods_id'    => $v['id'],
                'name'        => $v['name'],
                'short_name'  => $v['short_name'],
                'description' => $v['description'],
                'price'       => $v['price'],
                'pic'         => $v['pic'],
                'num'         => $v['num'],
                'num_price'   => $v['num_price'],
                'box_fee'     => $v['box_fee'],
                'create_date' => date('Y-m-d'),
            ];
        }
        if ($orderGoods) LihuaOrderGoods::insertAll($orderGoods);

        $this->success('OK', ['order_id' => $order_id, 'sn' => $sn]);
    }

    /**
     * 订单列表
     *
     * @ApiMethod   (POST)
     * @ApiHeaders  (name=token, type=string, required=true, description="请求的Token")
     * @ApiParams   (name="city_id", type="int", required=false, description="城市ID")
     * @ApiParams   (name="page", type="int", required=true, description="当前页，默认第1页")
     * @ApiParams   (name="page_size", type="int", required=false, description="每页条数，默认10条")
     * @ApiReturn   ({"code":1,"msg":"OK","time":"1573374133","data":{"page":1,"total":7,"page_size":10,"total_page":1,"list":[{"id":201,"sn":"1911434880963790","time":"2019-11-09 16:04","status":1,"status_text":"等待支付","goods":[{"id":1460,"name":"25元 秘制翅中饭","short_name":"翅中饭","price":25,"pic":"http://image.lihua.com/images/newweb/2015/11/thumb_56596b3ce997d.jpg","num":1,"num_price":25},{"id":2210,"name":"28元 糖醋排骨饭","short_name":"排骨+赠饮","price":28,"pic":"http://image.lihua.com/images/newweb/2016/04/thumb_57144be324714.jpg","num":1,"num_price":28}],"discount":10,"amount":48},{"id":152,"sn":"191023421430910","time":"2019-10-14 10:49","status":0,"status_text":"订单已取消","goods":[{"id":2911,"name":"促销38元套餐","short_name":"牛肉促","price":35,"pic":"http://image.lihua.com/images/newweb/2016/01/thumb_56a5dcdf0a1e0.JPG","num":1,"num_price":35}],"discount":0,"amount":23}]}})
     */
    public function index()
    {
        $city_id   = (int)$this->request->post('city_id', 0);
        $page      = max(1, (int)$this->request->post('page'));
        $page_size = (int)$this->request->post('page_size') ? : 10;
        $data      = [
            'page'       => $page,
            'total'      => 0,
            'page_size'  => $page_size,
            'total_page' => 0,
            'list'       => []
        ];

        $where['user_id'] = $this->auth->id;
        if ($city_id > 0) $where['city_id'] = $city_id;
        $total = LihuaOrder::where($where)->count();
        if ($total) {
            $data['total']      = $total;
            $data['total_page'] = ceil($total/$page_size);
            $list = LihuaOrder::where($where)->field('id,sn,order_amount,discount,status,create_time')
                ->order('id', 'desc')->page($page, $page_size)->select();
            $data['list'] = $this->reOrderList($list);
        }

        $this->success('OK', $data);
    }

    /**
     * 游客订单列表
     *
     * @ApiMethod   (POST)
     * @ApiParams   (name="sn", type="string", required=true, description="订单号组")
     * @ApiReturn   ({"code":1,"msg":"OK","time":"1573374469","data":{"list":[{"id":4,"sn":"190973870676869","time":"2019-09-06 16:46","status":0,"status_text":"订单已取消","goods":[{"id":1464,"name":"20元 蜜汁酱鸭饭","short_name":"酱鸭饭","price":20,"pic":"http://image.lihua.com/images/newweb/2018/03/thumb_5aae02a0dc1eb.jpg","num":1,"num_price":20},{"id":1654,"name":"原味奶茶","short_name":"奶茶","price":5,"pic":"http://image.lihua.com/images/newweb/2015/12/thumb_5660ef2ca54ca.jpg","num":1,"num_price":5},{"id":1659,"name":"骨肉相连","short_name":"骨肉相连","price":2,"pic":"http://image.lihua.com/images/newweb/2015/12/thumb_5660f1354f4ec.jpg","num":2,"num_price":4}],"discount":0,"amount":33},{"id":3,"sn":"190969600627237","time":"2019-09-06 16:41","status":1,"status_text":"等待支付","goods":[{"id":2035,"name":"板栗焖鸡拼外婆菜套餐","short_name":"板栗焖鸡拼外婆菜","price":20,"pic":"http://image.lihua.com/images/newweb/2015/12/thumb_566f632f56520.jpg","num":3,"num_price":60}],"discount":0,"amount":66}]}})
     */
    public function guestIndex()
    {
        $sn = $this->request->post('sn', '');
        if (!$sn) $this->error('参数错误');

        $list = LihuaOrder::whereIn('sn', $sn)->field('id,sn,order_amount,discount,status,create_time')
            ->order('id', 'desc')->select();

        $data = ['list' => $this->reOrderList($list)];
        $this->success('OK', $data);
    }

    /**
     * 重新组织订单列表数据
     *
     * @ApiInternal
     * @param array $list 订单列表
     * @return array
     */
    public function reOrderList($list = [])
    {
        $data = [];
        if ($list) {
            $ids    = array_column($list, 'id');
            $goods  = LihuaOrderGoods::ordersGoodsList($ids);
            $status = LihuaOrder::getStatusList();
            foreach ($list as $k => $v) {
                $data[] = [
                    'id'          => $v['id'],
                    'sn'          => $v['sn'],
                    'time'        => date("Y-m-d H:i", $v['create_time']),
                    'status'      => $v['status'],
                    'status_text' => isset($status[$v['status']]) ? $status[$v['status']] : '',
                    'goods'       => isset($goods[$v['id']]) ? $goods[$v['id']] : [],
                    'discount'    => round($v['discount'], 2),
                    'amount'      => round($v['order_amount'], 2),
                ];
            }
        }
        return $data;
    }


    /**
     * 订单详情
     *
     * @ApiMethod   (POST)
     * @ApiHeaders  (name=token, type=string, required=true, description="请求的Token,游客不传")
     * @ApiParams   (name="sn", type="int", required=true, description="订单号")
     * @ApiReturn   ({"code":1,"msg":"OK","time":"1573374575","data":{"id":65,"sn":"190952212390507","user_id":3,"city_id":3,"city_name":"常州","store_id":18,"store_name":"湖塘","consignee":"吴大帝","mobile":"13961259813","address":"中源大厦502室","lng":"119.949513","lat":"31.731623","packing_fee":2,"deliver_fee":3,"enough_name":"","enough_fee":10,"bonus_name":"10元新人红包","bonus_fee":10,"deliver_time":"2019-09-23 12:00:00","tableware":1,"invo_type":1,"invo_title":"吴大帝","invo_taxno":"","remark":"","goods_amount":53,"original_amount":58,"order_amount":38,"discount":20,"add_time":"2019-09-23 16:55:05","platform":"app","pay_type":"支付宝支付","pay_status":0,"pay_time":null,"confirm_time":null,"store_time":null,"rider_time":null,"finish_time":null,"cancel_time":null,"status":1,"create_time":1569228905,"update_time":1573202623,"status_text":"等待支付","goods":[{"id":1460,"name":"25元 秘制翅中饭","short_name":"翅中饭","price":25,"pic":"http://image.lihua.com/images/newweb/2015/11/thumb_56596b3ce997d.jpg","num":1,"num_price":25},{"id":2210,"name":"28元 糖醋排骨饭","short_name":"排骨+赠饮","price":28,"pic":"http://image.lihua.com/images/newweb/2016/04/thumb_57144be324714.jpg","num":1,"num_price":28}]}})
     */
    public function detail()
    {
        $sn  = $this->request->post('sn', '');
        $map = ['sn' => $sn];
        if ($this->token) $map['user_id'] = $this->auth->id;
        $row = LihuaOrder::get($map);
        if (!$row) $this->error('非法操作');

        $row['packing_fee']     = round($row['packing_fee'], 2);
        $row['deliver_fee']     = round($row['deliver_fee'], 2);
        $row['enough_fee']      = round($row['enough_fee'], 2);
        $row['bonus_fee']       = round($row['bonus_fee'], 2);
        $row['discount']        = round($row['discount'], 2);
        $row['goods_amount']    = round($row['goods_amount'], 2);
        $row['original_amount'] = round($row['original_amount'], 2);
        $row['order_amount']    = round($row['order_amount'], 2);

        $statusArr  = LihuaOrder::getStatusList();
        $row['status_text'] = $statusArr[$row['status']];

        $payTypeArr = LihuaCity::getPayTypeList();
        $row['pay_type'] = $row['pay_type'] > 0 ? $payTypeArr[$row['pay_type']] : '';

        $goods = LihuaOrderGoods::ordersGoodsList([$row['id']]);
        $row['goods'] = $goods[$row['id']];
        $this->success('OK', $row);
    }

    /**
     * 取消订单
     *
     * @ApiMethod   (POST)
     * @ApiHeaders  (name=token, type=string, required=true, description="请求的Token,游客不传")
     * @ApiParams   (name="sn", type="string", required=true, description="订单号")
     * @ApiReturn   ({"code":1,"msg":"OK","time":"1568696762","data":{}})
     */
    public function cancel()
    {
        $sn = $this->request->post('sn', '');
        if (!$sn) $this->error('参数错误');
        $order = LihuaOrder::getBySn($sn);
        if (!$order) $this->error('非法操作');

        if ($this->token) {
            if ($order->user_id != $this->auth->id) $this->error('无权操作');
        } else {
            if ($order->user_id != 0) $this->error('无权操作');
        }

        if ($order->status == 1) {
            $order->cancel_time = date('Y-m-d H:i:s');
            $order->status = 0;
            $order->save();
            if ($order->bonus_fee > 0 && $this->token) {//恢复用户红包
                LihuaUserbonus::update(['status' => 0, 'order_sn' => ''], ['user_id' => $this->auth->id, 'order_sn' => $sn]);
            }
            $this->success('OK');
        }
        $this->error('取消失败');
    }

    /**
     * 订单状态进度
     *
     * @ApiMethod   (POST)
     * @ApiHeaders  (name=token, type=string, required=true, description="请求的Token，游客不传")
     * @ApiParams   (name="sn", type="string", required=true, description="订单号")
     * @ApiReturn   ({"code":1,"msg":"OK","time":"1568740242","data":{"list":[{"status":"订单提交成功","time":"09-06 16:46","tips":"","pass":1,"ing":0},{"status":"订单已取消","time":"09-17 21:42","tips":"你取消了订单","pass":1,"ing":0}]}})
     */
    public function status()
    {
        $sn = $this->request->post('sn');
        if (!is_numeric($sn)) $this->error('参数错误');

        $user_id = $this->token ? $this->auth->id : 0;
        $list = LihuaOrder::getOrderProcess($sn, $user_id);
        $this->success('OK', ['list' => $list]);
    }

    /**
     * 评价订单
     *
     * @ApiMethod   (POST)
     * @ApiHeaders  (name=token, type=string, required=true, description="请求Token，游客不传")
     * @ApiParams   (name="sn", type="string", required=true, description="订单号")
     * @ApiParams   (name="content", type="string", required=false, description="评价内容")
     * @ApiParams   (name="goods_score", type="string", required=true, description="商品评分")
     * @ApiParams   (name="courier_score", type="string", required=true, description="骑手评分")
     * @ApiParams   (name="service_score", type="string", required=true, description="服务评分")
     * @ApiParams   (name="pics", type="string", required=false, description="评价图片")
     * @ApiReturn   ({"code":1,"msg":"OK","time":"1571479126","data":{}})
     */
    public function comment()
    {
        $sn = $this->request->post('sn');
        $content = $this->request->post('content', '');
        $goods_score   = (int)$this->request->post('goods_score', 0);
        $courier_score = (int)$this->request->post('courier_score', 0);
        $service_score = (int)$this->request->post('service_score', 0);
        $pics = $this->request->post('pics', '');

        if (!is_numeric($sn)) $this->error('参数错误');
        if ($goods_score == 0 || $courier_score == 0 || $service_score == 0) $this->error('你太懒了，请打个分');

        $row = LihuaOrder::where('sn', $sn)->field('id,city_id,store_id')->find();
        if (!$row) $this->error('非法操作');

        if (mb_strlen($content) > 200) $this->error('评价内容已超200字限制');

        $data = [
            'city_id'       => $row['city_id'],
            'store_id'      => $row['store_id'],
            'user_id'       => (int)$this->auth->id,
            'nickname'      => $this->auth->nickname ? : '',
            'order_id'      => $row['id'],
            'order_sn'      => $sn,
            'content'       => $content,
            'goods_score'   => $goods_score,
            'courier_score' => $courier_score,
            'service_score' => $service_score,
            'pics'          => $pics,
            'create_time'   => time(),
        ];

        try {
            \app\common\model\LihuaComment::create($data);
        } catch (Exception $e) {
            $this->error($e->getMessage());
        }

        $this->success('OK');
    }

}
